//===--- Passes/CallGraph.h -----------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//

#ifndef CALLGRAPH_H
#define CALLGRAPH_H

#include "hfsort.h"
#include "elf_reader.h"

namespace hfsort {

// Supported code layout algorithms
enum class Algorithm { Hfsort, HfsortPlus, PettisHansen, Invalid };

constexpr uint64_t InvalidAddr = std::numeric_limits<uint64_t>::max();

struct Func {
  Func(std::string name, uint64_t a, uint32_t g)
    : group(g)
    , addr(a)
    , mangledNames(1, name)
  {}

  bool valid() const { return mangledNames.size() > 0; }
  const uint32_t group;
  const uint64_t addr;
  std::vector<std::string> mangledNames;
};

struct MyCallGraph : TargetGraph {
  bool addFunc(std::string name, uint64_t addr, uint32_t size, uint32_t group);
  TargetId addrToTargetId(uint64_t addr) const;
  TargetId funcToTargetId(const std::string& func) const;

  std::string toString(TargetId id) const;

  std::vector<Func> funcs;
  std::map<uint64_t, TargetId> addr2TargetId;
  std::unordered_map<std::string, TargetId> func2TargetId;
};

// Maps symbol's start address to its name and size.
typedef std::map<uint64, std::pair<string, uint64> > AddressSymbolMap;

class SymbolReader : public ElfReader::SymbolSink {
 public:
  explicit SymbolReader(AddressSymbolMap *address_symbol_map)
      : address_symbol_map_(address_symbol_map) { }
  virtual void AddSymbol(const char *name, uint64 address, uint64 size) {
    if (size == 0) {
      return;
    }
    std::pair<AddressSymbolMap::iterator, bool> ret =
        address_symbol_map_->insert(
            std::make_pair(address, std::make_pair(string(name), size)));
  }
  virtual ~SymbolReader() { }
private:
  AddressSymbolMap *address_symbol_map_;
  
  DISALLOW_COPY_AND_ASSIGN(SymbolReader);
};
} // namespace hfsort

#endif
